package ca.mcgill.schedulability.singleevent.utils;

import ca.mcgill.model.implementation.Task;
import ca.mcgill.model.implementation.Transaction;
import ca.mcgill.schedulability.singleevent.functional.Bounds;
import ca.mcgill.schedulability.singleevent.model.SingleEventChain;

public class FindBounds {
	
	
	
	public Bounds findBounds(Transaction transactionIn, Transaction transaction) {

		int myLowerBound = -1; 
		int myUpperBound = -1;
		boolean doesInterfere = false;
		
		
		if (transaction.equals(transactionIn)){
			// Case 1: Task belongs to Transaction
			myLowerBound = 0;
			// update 05/04 --> based on Professor's feedback, we will check the whole 
			// transaction and compute dbf given its global deadline
			myUpperBound = transaction.getTasksInTransaction().size()-1; // Update -- upper bound = till the last task (was before last task)
			doesInterfere = true;
			
		}else{
			
			// Case 2: Task doesn't belong to Transaction
			// bug found --> you compare against the first task of Ti (transaction var in this case)
			Task taskFirstOfTransaction = transaction.getTasksInTransaction().get(0); 
			
			for (Task task : transactionIn.getTasksInTransaction()) {
				
				// Check the hp(src(T(tau_i))) tasks of the Transaction
				if (task.getPriority() > taskFirstOfTransaction.getPriority() ){
					
					myLowerBound = transactionIn.getTasksInTransaction().indexOf(task);
					myUpperBound = transactionIn.getTasksInTransaction().size() - 1; // upper bound = till the last task
					doesInterfere = true;
					break; 
				}
			}	
		}
		
		// create a new Bounds data structure
		Bounds myBounds = new Bounds(myUpperBound, myLowerBound, doesInterfere);
		return myBounds;
	
	}

	

	public Bounds findBoundsV2(Transaction transactionIn, Transaction transaction) {

		int myLowerBound = -1; 
		int myUpperBound = -1;
		boolean doesInterfere = false;
		boolean multipleTransc = false;
		
		
		if (transaction.equals(transactionIn)){
			// Case 1: Task belongs to Transaction
			myLowerBound = 0;
			// update 05/04 --> based on Professor's feedback, we will check the whole 
			// transaction and compute dbf given its global deadline
			myUpperBound = transaction.getTasksInTransaction().size()-1; // Update -- upper bound = till the last task (was before last task)
			doesInterfere = true;
			multipleTransc = false;

			
		}else{
			
			// Case 2: Task doesn't belong to Transaction
			Task taskFirstOfTransaction = transaction.getTasksInTransaction().get(0); 
			
			for (Task task : transactionIn.getTasksInTransaction()) {
				
				// Check the hp(src(T(tau_i))) tasks of the Transaction
				if (task.getPriority() > taskFirstOfTransaction.getPriority() ){
					
					myLowerBound = transactionIn.getTasksInTransaction().indexOf(task);
					myUpperBound = transactionIn.getTasksInTransaction().size() - 1; // upper bound = till the last task
					doesInterfere = true;
					break; 
				}
			}	
			
			// for the transactionIn to have multiple instances
			// its first task should have higher priority compared to the last 
			// task of transaction
			if (doesInterfere){
				
				Task taskFirstOfTransactionIn = transactionIn.getTasksInTransaction().get(0);
				Task taskLastOfTransaction = transaction.getTasksInTransaction().get(transaction.getTasksInTransaction().size()-1);
				
				if (taskFirstOfTransactionIn.getPriority()>taskLastOfTransaction.getPriority()){
					multipleTransc = true;
				}
				
			}
			
		}
		
		// create a new Bounds data structure
		Bounds myBounds = new Bounds(myUpperBound, myLowerBound, doesInterfere, multipleTransc);
		return myBounds;
	
	}

	
	
	
	
	
	// older version with "hard-coded" overall system (no transactions in Ernsest's code)
	public Bounds findBounds(SingleEventChain Ti, SingleEventChain T){
			
			int myLowerBound = -1; 
			int myUpperBound = -1;
			boolean doesInterfere = false;
			boolean multipleTransc = false;
			
			
			if (Ti.equals(T)){
				// Case 1: Task belongs to Transaction
				myLowerBound = 0;
				myUpperBound = T.getImplModel().getTasks().size() - 2; // upper bound = before the last task
				multipleTransc = false;
				doesInterfere = true;
				
			}else{
				
				// Case 2: Task doesn't belong to Transaction
				Task taskFirstOfT = T.getImplModel().getTasks().get(0); 
				
				for (Task task : Ti.getImplModel().getTasks()) {
					
					// Check the hp(src(T(tau_i))) tasks of the Transaction
					if (task.getPriority() > taskFirstOfT.getPriority() ){
						
						myLowerBound = Ti.getImplModel().getTasks().indexOf(task);
						myUpperBound = Ti.getImplModel().getTasks().size() - 1; // upper bound = before the last task
						if (myLowerBound==0){
							multipleTransc = true;
						}
						doesInterfere = true;
						break; 
					}
				}	
			}
			
			// create a new Bounds data structure
			Bounds myBounds = new Bounds(myUpperBound, myLowerBound, doesInterfere, multipleTransc);
			return myBounds;
			
		}


}
